package com.example.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import com.example.common.Result;
import com.example.common.ResultCode;
import com.example.entity.UserInfo;
import com.example.service.UserInfoService;
import com.example.exception.CustomException;
import com.example.vo.UserInfoVo;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户信息管理控制器
 * 提供用户信息的CRUD操作、分页查询及批量导入功能
 */
@RestController
@RequestMapping(value = "/userInfo")
public class UserInfoController {

    @Resource
    private UserInfoService userInfoService;

    /**
     * 添加用户信息
     * @param userInfo 用户信息传输对象（包含姓名、密码等必填字段）
     * @return {@link Result} 包含新增用户信息的结果对象
     */
    @PostMapping
    public Result<UserInfo> add(@RequestBody UserInfoVo userInfo) {
        userInfoService.add(userInfo);
        return Result.success(userInfo);
    }

    /**
     * 删除指定ID的用户
     * @param id 用户ID（路径参数）
     * @return {@link Result} 操作结果对象
     */
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Long id) {
        userInfoService.delete(id);
        return Result.success();
    }

    /**
     * 更新用户信息
     * @param userInfo 包含更新信息的用户传输对象（必须包含有效ID）
     * @return {@link Result} 操作结果对象
     */
    @PutMapping
    public Result update(@RequestBody UserInfoVo userInfo) {
        userInfoService.update(userInfo);
        return Result.success();
    }

    /**
     * 获取用户详情
     * @param id 用户ID（路径参数）
     * @return {@link Result} 包含用户详细信息的结果对象
     */
    @GetMapping("/{id}")
    public Result<UserInfo> detail(@PathVariable Long id) {
        UserInfo userInfo = userInfoService.findById(id);
        return Result.success(userInfo);
    }

    /**
     * 获取所有用户列表（不分页）
     * @return {@link Result} 包含用户传输对象列表的结果对象
     */
    @GetMapping
    public Result<List<UserInfoVo>> all() {
        return Result.success(userInfoService.findAll());
    }

    /**
     * 分页查询用户信息（支持按姓名搜索）
     * @param name 搜索关键词（姓名模糊查询）
     * @param pageNum 当前页码（默认1）
     * @param pageSize 每页显示数量（默认5）
     * @param request HTTP请求对象（用于获取请求上下文）
     * @return {@link Result} 包含分页数据的结果对象（PageInfo封装分页信息）
     */
    @GetMapping("/page/{name}")
    public Result<PageInfo<UserInfoVo>> page(@PathVariable String name,
                                             @RequestParam(defaultValue = "1") Integer pageNum,
                                             @RequestParam(defaultValue = "5") Integer pageSize,
                                             HttpServletRequest request) {
        return Result.success(userInfoService.findPage(name, pageNum, pageSize, request));
    }

    /**
     * 用户注册接口
     * @param userInfo 包含用户名和密码的用户对象
     * @return {@link Result} 操作结果对象
     * @throws CustomException 当用户名或密码为空时抛出参数错误异常（状态码：PARAM_ERROR）
     */
    @PostMapping("/register")
    public Result<UserInfo> register(@RequestBody UserInfo userInfo) {
        if (StrUtil.isBlank(userInfo.getName()) || StrUtil.isBlank(userInfo.getPassword())) {
            throw new CustomException(ResultCode.PARAM_ERROR);
        }
        return Result.success(userInfoService.add(userInfo));
    }

    /**
     * 批量导入用户信息（Excel文件）
     * @param file 上传的Excel文件（支持.xlsx格式）
     * @return {@link Result} 操作结果对象
     * @throws IOException 文件读取异常
     * @implNote 使用Hutool的ExcelUtil解析文件，自动过滤name字段为空的记录，
     * 批量插入有效数据到数据库，保留原始数据顺序
     */
    @PostMapping("/upload")
    public Result upload(MultipartFile file) throws IOException {
        List<UserInfo> infoList = ExcelUtil.getReader(file.getInputStream()).readAll(UserInfo.class);
        if (!CollUtil.isEmpty(infoList)) {
            List<UserInfo> resultList = infoList.stream()
                    .filter(x -> ObjectUtil.isNotEmpty(x.getName()))
                    .collect(Collectors.toList());
            resultList.forEach(userInfoService::add);
        }
        return Result.success();
    }
}